#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
#include <vector>
#include <stdio.h>
#include<conio.h>
#include<math.h>

using namespace cv;
using namespace std;



Mat encoder(Mat src,int L)
{
	src.convertTo(src,CV_16S);
	
	Mat V= Mat(src.rows,src.cols,CV_16S,Scalar(0,0,0));
	Mat ENC= Mat(src.rows,src.cols,CV_16S,Scalar(0,0,0));
	V=src;   // for level=-1

	_int16 d,dm1,dm2,dp1,dp2;
	_int16 s,sm1,sm2,sp1,sp2;

	for(int l=1;l<=L;l++)
	{
		if(l!=1){
			V=V(Rect(0,0,V.cols/2,V.rows/2));}
		cout<<"size of V="<<V.size()<<endl;
		Mat v= Mat(V.rows,V.cols,CV_16S,Scalar(0,0,0));
	for(int j=0;j<V.rows;j++)
	{
		for(int i=0;i<V.cols;i=i+2)
		{
			d=dm1=dm2=dp1=dp2=0;
			s=sm1=sm2=sp1=sp2=0;
			if(i+1>=0 && i+1<V.cols)
				d=V.at<_int16>(j,i+1);
			if(i-1>=0 && i-1<V.cols)
				dm1=V.at<_int16>(j,i-1);
			if(i-3>=0 && i-3<V.cols)
				dm2=V.at<_int16>(j,i-3);
			if(i+3>=0 && i+3<V.cols)	
				dp1=V.at<_int16>(j,i+3);
			if(i+5>=0 && i+5<V.cols)
				dp2=V.at<_int16>(j,i+5);
			
			if(i>=0 && i<V.cols)
				s=V.at<_int16>(j,i);
			if(i-2>=0 && i-2<V.cols)
				sm1=V.at<_int16>(j,i-2);
			if(i-4>=0 && i-4<V.cols)
				sm2=V.at<_int16>(j,i-4);
			if(i+2>=0 && i+2<V.cols)	
				sp1=V.at<_int16>(j,i+2);
			if(i+4>=0 && i+4<V.cols)
				sp2=V.at<_int16>(j,i+4);
			
			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d-floor((float)s/5.0+0.5);
			if(i-1>=0 && i-1<V.cols)
				dm1=dm1-floor((float)sm1/5.0+0.5);
			if(i-3>=0 && i-3<V.cols)
				dm2=dm2-floor((float)sm2/5.0+0.5);
			if(i+3>=0 && i+3<V.cols)	
				dp1=dp1-floor((float)sp1/5.0+0.5);
			if(i+5>=0 && i+5<V.cols)
				dp2=dp2-floor((float)sp2/5.0+0.5);

			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			s=s-floor((float)(15*dm1+5*d)/24.0+0.5);
			if(i-2>=0 && i-2<V.cols)
				sm1=sm1-floor((float)(15*dm2+5*dm1)/24.0+0.5);
			if(i+2>=0 && i+2<V.cols)	
				sp1=sp1-floor((float)(15*d+5*dp1)/24.0+0.5);
			if(i+4>=0 && i+4<V.cols)
				sp2=sp2-floor((float)(15*dp1+5*dp2)/24.0+0.5);
			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			d=d-floor((float)(15*s+9*sp1)/10.0+0.5);
			if(i-1>=0 && i-1<V.cols)
				dm1=dm1-floor((float)(15*sm1+9*s)/10.0+0.5);
			if(i+3>=0 && i+3<V.cols)	
				dp1=dp1-floor((float)(15*sp1+9*sp2)/10.0+0.5);
			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			s=s-floor((float)(-5*dm1-24*d+5*dp1)/72.0+0.5);

			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			s=s-floor((float)d+0.5);

			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d+floor((float)s*(1-1.0/3.0/sqrt(2.0))+0.5);

			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			s=s+floor((float)d*3.0*sqrt(2.0)+0.5);

			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d+floor((float)s*(1/18.0-1/3.0/sqrt(2.0))+0.5);

			if(i==0 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			

			v.at<_int16>(j,(i)/2)=s;
			v.at<_int16>(j,(i)/2+V.cols/2)=d;
			/*
			if(max<s || max<d)
				max=s>d?s:d;
			if(min>s || min>d)
				min=s<d?s:d;
				*/
		}
	}
	
	cout<<"filtering and sampling along rows"<<endl;
	
	for(int j=0;j<v.cols;j++)
	{
		//cout<<"j="<<j<<endl;
		for(int i=0;i<v.rows;i=i+2)
		{
			//cout<<"i="<<i<<endl;
			d=dm1=dm2=dp1=dp2=0;
			s=sm1=sm2=sp1=sp2=0;
			if(i+1>=0 && i+1<v.rows)
				d=v.at<_int16>(i+1,j);
			if(i-1>=0 && i-1<v.rows)
				dm1=v.at<_int16>(i-1,j);
			if(i-3>=0 && i-3<v.rows)
				dm2=v.at<_int16>(i-3,j);
			if(i+3>=0 && i+3<v.rows)
				dp1=v.at<_int16>(i+3,j);
			if(i+5>=0 && i+5<v.rows)
				dp2=v.at<_int16>(i+5,j);
			
			if(i>=0 && i<v.rows)
				s=v.at<_int16>(i,j);
			if(i-2>=0 && i-2<v.rows)
				sm1=v.at<_int16>(i-2,j);
			if(i-4>=0 && i-4<v.rows)
				sm2=v.at<_int16>(i-4,j);
			if(i+2>=0 && i+2<v.rows)	
				sp1=v.at<_int16>(i+2,j);
			if(i+4>=0 && i+4<v.rows)
				sp2=v.at<_int16>(i+4,j);
			
			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d-floor((float)s/5.0+0.5); 
			
				if(i-1>=0 && i-1<v.rows)
					dm1=dm1-floor((float)sm1/5.0+0.5);
				if(i-3>=0 && i-3<v.rows)
					dm2=dm2-floor((float)sm2/5.0+0.5);
				if(i+3>=0 && i+3<v.rows)
					dp1=dp1-floor((float)sp1/5.0+0.5);
				if(i+5>=0 && i+5<v.rows)
					dp2=dp2-floor((float)sp2/5.0+0.5);
			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			s=s-floor((float)(15*dm1+5*d)/24.0+0.5);
			if(i-2>=0 && i-2<v.rows)
				sm1=sm1-floor((float)(15*dm2+5*dm1)/24.0+0.5);
			if(i+2>=0 && i+2<v.rows)	
				sp1=sp1-floor((float)(15*d+5*dp1)/24.0+0.5);
			if(i+4>=0 && i+4<v.rows)
				sp2=sp2-floor((float)(15*dp1+5*dp2)/24.0+0.5);
			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			d=d-floor((float)(15*s+9*sp1)/10.0+0.5);
			if(i-1>=0 && i-1<v.rows)
				dm1=dm1-floor((float)(15*sm1+9*s)/10.0+0.5);
			if(i+3>=0 && i+3<v.rows)
				dp1=dp1-floor((float)(15*sp1+9*sp2)/10.0+0.5);

			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			s=s-floor((float)(-5*dm1-24*d+5*dp1)/72.0+0.5);

			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			s=s-floor((float)d+0.5);

			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d+floor((float)s*(1-1.0/3.0/sqrt(2.0))+0.5);

			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			s=s+floor((float)d*3.0*sqrt(2.0)+0.5);

			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d+floor((float)s*(1/18.0-1/3.0/sqrt(2.0))+0.5);

			if(j==0 && i==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			V.at<_int16>((i)/2,j)=s;
			V.at<_int16>((i)/2+v.rows/2,j)=d;
			/*
			if(max<s || max<d)
				max=s>d?s:d;
			if(min>s || min>d)
				min=s<d?s:d;
				*/
		}
	}
	/*
	if(l==3)
	{
		cvNamedWindow("win");
		imshow("win",V);
		cvWaitKey(0);
	}
	*/
	V.copyTo(ENC(Rect(0,0,src.cols/pow(2,l-1),src.rows/pow(2,l-1))));
}
return ENC;
}


Mat decoder(Mat enc,int L)
{
	
	
	_int16 d,dm1,dm2,dp1,dp2;
	_int16 s,sm1,sm2,sp1,sp2;
	
	cout<<"decoding along the rows";
	for(int l=L;l>0;l--)
	{
		Mat ENC=enc(Rect(0,0,enc.cols/pow(2,l-1),enc.rows/pow(2,l-1)));
		Mat dec1=Mat(ENC.rows,ENC.cols,CV_16S,Scalar(0,0,0));
	for(int j=0;j<ENC.cols;j++)
	{
		for(int i=ENC.rows/2-1;i>=0;i--)
		{
			d=dm1=dm2=dp1=dp2=0;
			s=sm1=sm2=sp1=sp2=0;

			s=ENC.at<_int16>(i,j);
			d=ENC.at<_int16>(i+ENC.rows/2,j);
			
			if(i+ENC.rows/2-1>=ENC.rows/2 && i+ENC.rows/2-1<ENC.rows)
				dm1=ENC.at<_int16>(i+ENC.rows/2-1,j);
			if(i+ENC.rows/2-2>=ENC.rows/2 && i+ENC.rows/2-2<ENC.rows)
				dm2=ENC.at<_int16>(i+ENC.rows/2-2,j);
			if(i+ENC.rows/2+1>=ENC.rows/2 && i+ENC.rows/2+1<ENC.rows)
				dp1=ENC.at<_int16>(i+ENC.rows/2+1,j);
			if(i+ENC.rows/2+2>=ENC.rows/2 && i+ENC.rows/2+2<ENC.rows)
				dp2=ENC.at<_int16>(i+ENC.rows/2+2,j);
			
			if(i-1>=0 && i-1<ENC.rows/2)
				sm1=ENC.at<_int16>(i-1,j);
			if(i-2>=0 && i-2<ENC.rows/2)
				sm2=ENC.at<_int16>(i-2,j);
			if(i+1>=0 && i+1<ENC.rows/2)
				sp1=ENC.at<_int16>(i+1,j);
			if(i+2>=0 && i+2<ENC.rows/2)
				sp2=ENC.at<_int16>(i+2,j);

			d=d-floor((float)s*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2-1>=ENC.rows/2 && i+ENC.rows/2-1<ENC.rows)
				dm1=dm1-floor((float)sm1*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2-2>=ENC.rows/2 && i+ENC.rows/2-2<ENC.rows)
				dm2=dm2-floor((float)sm2*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2+1>=ENC.rows/2 && i+ENC.rows/2+1<ENC.rows)
				dp1=dp1-floor((float)sp1*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2+2>=ENC.rows/2 && i+ENC.rows/2+2<ENC.rows)
				dp2=dp2-floor((float)sp2*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			s=s-floor((float)d*3.0*sqrt(2.0)+0.5);
			if(i-1>=0 && i-1<ENC.rows/2)
				sm1=sm1-floor((float)dm1*3.0*sqrt(2.0)+0.5);
			if(i-2>=0 && i-2<ENC.rows/2)
				sm2=sm2-floor((float)dm2*3.0*sqrt(2.0)+0.5);
			if(i+1>=0 && i+1<ENC.rows/2)
				sp1=sp1-floor((float)dp1*3.0*sqrt(2.0)+0.5);
			if(i+2>=0 && i+2<ENC.rows/2)
				sp2=sp2-floor((float)dp2*3.0*sqrt(2.0)+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d-floor((float)s*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2-1>=ENC.rows/2 && i+ENC.rows/2-1<ENC.rows)
				dm1=dm1-floor((float)sm1*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2-2>=ENC.rows/2 && i+ENC.rows/2-2<ENC.rows)
				dm2=dm2-floor((float)sm2*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2+1>=ENC.rows/2 && i+ENC.rows/2+1<ENC.rows)
				dp1=dp1-floor((float)sp1*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+ENC.rows/2+2>=ENC.rows/2 && i+ENC.rows/2+2<ENC.rows)
				dp2=dp2-floor((float)sp2*(1-1.0/3.0/sqrt(2.0))+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			s=s+floor((float)d+0.5);
			if(i-1>=0 && i-1<ENC.rows/2)
				sm1=sm1+floor((float)dm1+0.5);
			if(i-2>=0 && i-2<ENC.rows/2)
				sm2=sm2+floor((float)dm2+0.5);
			if(i+1>=0 && i+1<ENC.rows/2)
				sp1=sp1+floor((float)dp1+0.5);
			if(i+2>=0 && i+2<ENC.rows/2)
				sp2=sp2+floor((float)dp2+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			//ENC.at<_int16>(i,j)=s;
//ENC.at<_int16>(i+ENC.rows/2,j)=d;
	
			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
				
			s=s+floor((float)(-5*dm1-24*d+5*dp1)/72.0+0.5);
			if(i-1>=0 && i-1<ENC.rows/2)
				sm1=sm1+floor((float)(-5*dm2-24*dm1+5*d)/72.0+0.5);
			if(i+1>=0 && i+1<ENC.rows/2)
				sp1=sp1+floor((float)(-5*d-24*dp1+5*dp2)/72.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			d=d+floor((float)(15*s+9*sp1)/10.0+0.5);
			if(i+ENC.rows/2-1>=ENC.rows/2 && i+ENC.rows/2-1<ENC.rows)
				dm1=dm1+floor((float)(15*sm1+9*s)/10.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
	
			s=s+floor((float)(15*dm1+5*d)/24.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			d=d+floor((float)s/5.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			dec1.at<_int16>(2*i,j)=s;
			dec1.at<_int16>(2*i+1,j)=d;

		}
	}
	
	cout<<"decoding along the columns"<<endl;

	Mat dec2=Mat(dec1.rows,dec1.cols,CV_16S,Scalar(0,0,0));

	for(int j=0;j<dec1.rows;j++)
	{
		for(int i=dec1.cols/2-1;i>=0;i--)
		{
			
			//dec2.at<_int16>(j,2*i)=dec1.at<_int16>(j,i)-floor((dec1.at<_int16>(j,i+dec1.cols/2))/2);
			//dec2.at<_int16>(j,2*i+1)=dec2.at<_int16>(j,2*i)+dec1.at<_int16>(j,i+dec1.cols/2);
			
			//cout<<(int)dec2.at<_int16>(2*i,j)<<" "<<(int)dec2.at<_int16>(2*i+1,j)<<endl;
			d=dm1=dm2=dp1=dp2=0;
			s=sm1=sm2=sp1=sp2=0;

			s=dec1.at<_int16>(j,i);
			d=dec1.at<_int16>(j,i+dec1.cols/2);
			
			if(i+dec1.cols/2-1>=dec1.cols/2 && i+dec1.cols/2-1<dec1.cols)
				dm1=dec1.at<_int16>(j,i+dec1.cols/2-1);
			if(i+dec1.cols/2-2>=dec1.cols/2 && i+dec1.cols/2-2<dec1.cols)
				dm2=dec1.at<_int16>(j,i+dec1.cols/2-2);
			if(i+dec1.cols/2+1>=dec1.cols/2 && i+dec1.cols/2+1<dec1.cols)
				dp1=dec1.at<_int16>(j,i+dec1.cols/2+1);
			if(i+dec1.cols/2+2>=dec1.cols/2 && i+dec1.cols/2+2<dec1.cols)
				dp2=dec1.at<_int16>(j,i+dec1.cols/2+2);

			if(i-1>=0 && i-1<dec1.cols/2)
				sm1=dec1.at<_int16>(j,i-1);
			if(i-2>=0 && i-2<dec1.cols/2)
				sm2=dec1.at<_int16>(j,i-2);
			if(i+1>=0 && i+1<dec1.cols/2)
				sp1=dec1.at<_int16>(j,i+1);
			if(i+2>=0 && i+2<dec1.cols/2)
				sp2=dec1.at<_int16>(j,i+2);
			

			d=d-floor((float)s*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2-1>=dec1.cols/2 && i+dec1.cols/2-1<dec1.cols)
				dm1=dm1-floor((float)sm1*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2-2>=dec1.cols/2 && i+dec1.cols/2-2<dec1.cols)
				dm2=dm2-floor((float)sm2*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2+1>=dec1.cols/2 && i+dec1.cols/2+1<dec1.cols)
				dp1=dp1-floor((float)sp1*(1/18.0-1/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2+2>=dec1.cols/2 && i+dec1.cols/2+2<dec1.cols)
				dp2=dp2-floor((float)sp2*(1/18.0-1/3.0/sqrt(2.0))+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			s=s-floor((float)d*3.0*sqrt(2.0)+0.5);
			if(i-1>=0 && i-1<dec1.cols/2)
				sm1=sm1-floor((float)dm1*3.0*sqrt(2.0)+0.5);
			if(i-2>=0 && i-2<dec1.cols/2)
				sm2=sm2-floor((float)dm2*3.0*sqrt(2.0)+0.5);
			if(i+1>=0 && i+1<dec1.cols/2)
				sp1=sp1-floor((float)dp1*3.0*sqrt(2.0)+0.5);
			if(i+2>=0 && i+2<dec1.cols/2)
				sp2=sp2-floor((float)dp2*3.0*sqrt(2.0)+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			d=d-floor((float)s*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2-1>=dec1.cols/2 && i+dec1.cols/2-1<dec1.cols)
				dm1=dm1-floor((float)sm1*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2-2>=dec1.cols/2 && i+dec1.cols/2-2<dec1.cols)
				dm2=dm2-floor((float)sm2*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2+1>=dec1.cols/2 && i+dec1.cols/2+1<dec1.cols)
				dp1=dp1-floor((float)sp1*(1-1.0/3.0/sqrt(2.0))+0.5);
			if(i+dec1.cols/2+2>=dec1.cols/2 && i+dec1.cols/2+2<dec1.cols)
				dp2=dp2-floor((float)sp2*(1-1.0/3.0/sqrt(2.0))+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

			s=s+floor((float)d+0.5);
			if(i-1>=0 && i-1<dec1.cols/2)
				sm1=sm1+floor((float)dm1+0.5);
			if(i-2>=0 && i-2<dec1.cols/2)
				sm2=sm2+floor((float)dm2+0.5);
			if(i+1>=0 && i+1<dec1.cols/2)
				sp1=sp1+floor((float)dp1+0.5);
			if(i+2>=0 && i+2<dec1.cols/2)
				sp2=sp2+floor((float)dp2+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}

//dec1.at<_int16>(j,i)=s;
//dec1.at<_int16>(j,i+dec1.cols/2)=d;

			
			
			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
				
			s=s+floor((float)(-5*dm1-24*d+5*dp1)/72.0+0.5);
			if(i-1>=0 && i-1<dec1.cols/2)
				sm1=sm1+floor((float)(-5*dm2-24*dm1+5*d)/72.0+0.5);
			if(i+1>=0 && i+1<dec1.cols/2)
				sp1=sp1+floor((float)(-5*d-24*dp1+5*dp2)/72.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			/*
			if(i+1>=0 && i+1<dec1.cols)
				sp1=sp1+floor((float)(-5*d-24*dp1+5*dp2)/72.0+0.5);
				*/
	
			d=d+floor((float)(15*s+9*sp1)/10.0+0.5);
			if(i+dec1.cols/2-1>=dec1.cols/2 && i+dec1.cols/2-1<dec1.cols)
				dm1=dm1+floor((float)(15*sm1+9*s)/10.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			/*
			if(i+dec1.cols/2-1>=0 && i+dec1.cols/2-1<dec1.cols)
				dm1=dm1+floor((float)(15*sm1+9*s)/10.0+0.5);
				*/

			s=s+floor((float)(15*dm1+5*d)/24.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			d=d+floor((float)s/5.0+0.5);

			if(i==0/2 && j==500)
			{
				cout<<"s="<<s<<", d="<<d<<",dm1= "<<dm1<<",dm2="<<dm2<<",dp1= "<<dp1<<",dp2= "<<dp2<<endl;
			}
			
			dec2.at<_int16>(j,2*i)=s;
			dec2.at<_int16>(j,2*i+1)=d;

		}
	}
	/*
	if(l==1)
	{
		cvNamedWindow("win");
		dec2.convertTo(dec2,CV_8U);
		imshow("win",dec2);
		cvWaitKey(0);
	}
	*/
	dec2.copyTo(enc(Rect(0,0,enc.cols/pow(2,l-1),enc.rows/pow(2,l-1))));
	}
	return enc;
}

void detail_encoder(int data[],int size,int dict[],vector<int>* detail_error_bits,int** detail_quant_data)
{
	int* error=new int[size];
	
	//float m;
	for(int i=0;i<size;i++)
	{
		//std::cout<<"Itertion "<<i<<std::endl;
		//std::cout<<"data= "<<data[i];
		int k=0;
		int max_err_bits,err_bits;
		while(dict[k]<data[i] && dict[k+1]<=data[i])
			k++;
		(*detail_quant_data)[i]=dict[k];
		//std::cout<<"Quantised data ="<<quant_data[i]<<std::endl;
		error[i]=data[i]-(*detail_quant_data)[i];
		//std::cout<<"Error= "<<error[i]<<std::endl;
		if((*detail_quant_data)[i]==0)
			max_err_bits=1;
		else
			max_err_bits=log((*detail_quant_data)[i])/log(2);
		if(error[i]==0 || error[i]==1)
			err_bits=1;
		else
		{
			err_bits=ceil(log(error[i])/log(2));
			//std::cout<<'\n'<<err_bits<<'\n';
			if(log(error[i])/log(2)==err_bits)
				err_bits=err_bits+1;
			//std::cout<<'\n'<<err_bits<<'\n';
		}
		//std::cout<<"max err bits="<<max_err_bits<<"and err bits="<<err_bits<<'\n';



		//std::cout<<"No of zeros needed="<<max_err_bits-err_bits<<'\n';
		for(int j=0;j<max_err_bits-err_bits;j++)
			(*detail_error_bits).push_back(0);
		
		k=error[i];
		std::vector<int> bits;
		while(k!=0)
		{
		//std::cout<<'\n'<<"k="<<k<<'\n';
		bits.push_back(k%2);
		//i++;
		k=k/2;
		}
		/*
		for(int l=0;l<bits.size();l++)
			std::cout<<bits[l]<<" ";
		std::cout<<'\n';
		*/
		//bin=dectobin(error[i]);
		if(bits.empty())
			(*detail_error_bits).push_back(0);
		else
		{
		for(int j=bits.size()-1;j>=0;j--)
			{
			(*detail_error_bits).push_back(bits.back()>0);
			bits.pop_back();
			}
		}
		/*
		for(int l=0;l<error_bits.size();l++)
			std::cout<<error_bits[l]<<" ";
			std::cout<<'\n';
			*/
	}
	
}

int* detail_decoder(int qunt_data[],std::vector<int> err_bits,int size)
{
	int* input=new int[size];
	int num=0,k=0,j,bit_read;
	for(int i=0;i<size;i++)
	{
	num=0;
	if(qunt_data[i]!=0)
		bit_read=log(qunt_data[i])/log(2);
	else
		bit_read=1;
	for(j=k;j<bit_read+k;j++)
		num=num*2+err_bits[j];
	k=j;
	input[i]=num+qunt_data[i];
	}
	return input;
}


// DPCM encoder and decoder

void dpcm_encoder(int data[],int size,int dict[],int** dpcm,int** dpcm_sign_bits,int** quant_data,vector<int>* error_bits)
{
	int* error=new int[size];
	//float m;
	(*dpcm)[0]=data[0];
	(*dpcm_sign_bits)[0]=0;
	for(int i=1;i<size;i++)
	{
		(*dpcm)[i]=data[i]-data[i-1];
		if((*dpcm)[i]<0)
			(*dpcm_sign_bits)[i]=1;
		else
			(*dpcm_sign_bits)[i]=0;
		(*dpcm)[i]=abs((*dpcm)[i]);
	}

	for(int i=0;i<size;i++)
	{
		//std::cout<<"Itertion "<<i<<std::endl;
		//std::cout<<"data= "<<data[i];
		int k=0;
		int max_err_bits,err_bits;
		while(dict[k]<(*dpcm)[i] && dict[k+1]<=(*dpcm)[i])
			k++;
		(*quant_data)[i]=dict[k];
		//std::cout<<"Quantised data ="<<(*quant_data)[i]<<std::endl;
		error[i]=(*dpcm)[i]-(*quant_data)[i];
		//std::cout<<"Error= "<<error[i]<<std::endl;
		if((*quant_data)[i]==0)
			max_err_bits=1;
		else
			max_err_bits=log((*quant_data)[i])/log(2);
		if(error[i]==0 || error[i]==1)
			err_bits=1;
		else
		{
			err_bits=ceil(log(error[i])/log(2));
			//std::cout<<'\n'<<err_bits<<'\n';
			if(log(error[i])/log(2)==err_bits)
				err_bits=err_bits+1;
			//std::cout<<'\n'<<err_bits<<'\n';
		}
		//std::cout<<"max err bits="<<max_err_bits<<"and err bits="<<err_bits<<'\n';



		//std::cout<<"No of zeros needed="<<max_err_bits-err_bits<<'\n';
		for(int j=0;j<max_err_bits-err_bits;j++)
			(*error_bits).push_back(0);
		
		k=error[i];
		std::vector<int> bits;
		while(k!=0)
		{
		//std::cout<<'\n'<<"k="<<k<<'\n';
		bits.push_back(k%2);
		//i++;
		k=k/2;
		}/*
		for(int l=0;l<bits.size();l++)
			std::cout<<bits[l]<<" ";
		std::cout<<'\n';
		*/
		//bin=dectobin(error[i]);
		if(bits.empty())
			(*error_bits).push_back(0);
		else
		{
		for(int j=bits.size()-1;j>=0;j--)
			{
			(*error_bits).push_back(bits.back()>0);
			bits.pop_back();
			}
		}/*
		for(int l=0;l<(*error_bits).size();l++)
			std::cout<<(*error_bits)[l]<<" ";
			std::cout<<'\n';*/
	}

}

int* dpcm_decoder(int qunt_data[],int signbit[],std::vector<int> err_bits,int size)
{
	//std::cout<<"hello";
	//cout<<"size="<<size;
	//cout<<"errorbits size="<<err_bits.size()<<endl;
	int* input=new int[size];
	int num=0,k=0,j,bit_read;
	for(int i=0;i<size;i++)
	{
		//cout<<"i="<<i<<endl;
	num=0;
	//std::cout<<qunt_data[i]<<'\n';
	if(qunt_data[i]!=0)
		bit_read=log(qunt_data[i])/log(2);
	else
		bit_read=1;
	//cout<<"bit read="<<bit_read<<'\n';
	for(j=k;j<bit_read+k;j++)             // && j<err_bits.size()
	{
		//std::cout<<"j="<<j<<'\n';
		num=num*2+(err_bits[j]);
	}
	//cout<<"num= "<<num<<'\n';
	k=j;
	input[i]=num+qunt_data[i];
	input[i]=input[i]*pow(-1,signbit[i]);
	
	if(i>0)
		input[i]+=input[i-1];
	//cout<<"input["<<i<<"]="<<input[i];
	}
	//cout<<"affgghhh";
	return input;
}

vector<int> huff_encoder1(int quant_data[],int size)
{
	vector<int> encoded;
	int c[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	for(int i=0;i<size;i++)
	{
		if(quant_data[i]==0)
			c[0]++;
		else
			c[(int)(log(quant_data[i])/log(2))]++;
		//cout<<"i="<<i;
		//cout<<" k= "<<encoded.size()<<endl;
		if(quant_data[i]==0)
		{
			for(int j=0;j<12;j++)
				encoded.push_back(1);
		}
		else if(quant_data[i]==2)
		{
			for(int j=0;j<10;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==4)
		{
			for(int j=0;j<9;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==8)
		{
			for(int j=0;j<8;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==16)
		{
			for(int j=0;j<7;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==32)
		{
			for(int j=0;j<6;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==64)
		{
			for(int j=0;j<5;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==128)
		{
			for(int j=0;j<3;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==256)
		{
			encoded.push_back(0);
			encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==512)
		{
			encoded.push_back(1);
			encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==1024)
		{
			encoded.push_back(1);
			encoded.push_back(0);
		}
		else if(quant_data[i]==2048)
		{
			encoded.push_back(0);
			encoded.push_back(0);
		}
		else if(quant_data[i]==4096)
		{
			//cout<<"4096 starts at "<<encoded.size()<<endl;
			encoded.push_back(0);
			encoded.push_back(1);
			encoded.push_back(1);
		}
		else if(quant_data[i]==8192)
		{
			//cout<<"8192 starts at "<<encoded.size()<<endl;
			encoded.push_back(1);
			encoded.push_back(1);
			encoded.push_back(1);
			encoded.push_back(1);
			encoded.push_back(0);
			//break;
		}
		else if(quant_data[i]==16384)
		{
			for(int j=0;j<11;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
	}
	/*
	for(int i=0;i<16;i++)
	{
		cout<<"no."<<pow(2,i)<<" "<<c[i]<<"times"<<endl;
	}*/
	return encoded;
}

int* huff_decoder1(vector<int> huff_bits,int size)
{
	int* data=new int[size];
	int k=0;
	int c[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	
	for(int i=0;i<size;i++)
	//int i=0;
	//while(k<huff_bits.size())
	{
		//cout<<"i="<<i;
		//cout<<" k="<<k<<endl;
		
		if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==0){
			
			data[i]=8192;
			k+=5;}
		//cout<<" 8192 found"<<endl;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==0){
			
			data[i]=1024;
			k+=2;
		}
		else if(huff_bits[k]==0 && huff_bits[k+1]==0){
			
			data[i]=2048;
			k+=2;}
		else if(huff_bits[k]==0 && huff_bits[k+1]==1 && huff_bits[k+2]==0 ){
			
			data[i]=256;
			k+=3;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==0 ){
			
			data[i]=512;
			k+=3;}
		else if(huff_bits[k]==0 && huff_bits[k+1]==1 && huff_bits[k+2]==1 ){
			
			data[i]=4096;
			k+=3;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==0){
			
			data[i]=128;
			k+=4;}
		
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==0){
			
			data[i]=64;
			k+=6;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==0){
			
			data[i]=32;
			k+=7;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==0){
			
			data[i]=16;
			k+=8;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==1 && huff_bits[k+8]==0){
			
			data[i]=8;
			k+=9;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==1 && huff_bits[k+8]==1 && huff_bits[k+9]==0){
			
			data[i]=4;
			k+=10;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==1 && huff_bits[k+8]==1 && huff_bits[k+9]==1 && huff_bits[k+10]==0){
			
			data[i]=2;
			k+=11;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==1 && huff_bits[k+8]==1 && huff_bits[k+9]==1 && huff_bits[k+10]==1 && huff_bits[k+11]==1){
			
			data[i]=0;
			k+=12;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1 && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==1 && huff_bits[k+8]==1 && huff_bits[k+9]==1 && huff_bits[k+10]==1 && huff_bits[k+11]==0){
			
			data[i]=16384;
			k+=12;}

		if(data[i]==0)
			c[0]++;
		else
			c[(int)(log(data[i])/log(2))]++;
		//if(data[i]==8192)
			//cout<<"k="<<k<<endl;
	}
	/*
	for(int i=0;i<16;i++)
	{
		cout<<"no."<<pow(2,i)<<" "<<c[i]<<"times"<<endl;
	}
	*/
		
	return data;
}

vector<int> huff_encoder2(int quant_data[],int size)
{
	vector<int> encoded;
	for(int i=0;i<size;i++)
	{
		if(quant_data[i]==0)
		{
			encoded.push_back(0);}
		if(quant_data[i]==2)
		{
			encoded.push_back(1);
			encoded.push_back(0);
			encoded.push_back(0);}
		if(quant_data[i]==4)
		{
			for(int j=0;j<2;j++)
				encoded.push_back(1);
			encoded.push_back(0);}
		if(quant_data[i]==8)
		{
			for(int j=0;j<2;j++){
				encoded.push_back(1);
				encoded.push_back(0);}}
		if(quant_data[i]==16)
		{
			for(int j=0;j<3;j++)
				encoded.push_back(1);
			encoded.push_back(0);}
		if(quant_data[i]==32)
		{
			encoded.push_back(1);
			encoded.push_back(0);
			for(int j=0;j<2;j++)
				encoded.push_back(1);
			encoded.push_back(0);}
		if(quant_data[i]==64)
		{
			encoded.push_back(1);
			encoded.push_back(0);
			for(int j=0;j<3;j++)
				encoded.push_back(1);}
		if(quant_data[i]==128)
		{
			for(int j=0;j<4;j++)
				encoded.push_back(1);
			encoded.push_back(0);}
		if(quant_data[i]==256)
		{
			for(int j=0;j<5;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		if(quant_data[i]==512)
		{
			for(int j=0;j<6;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		if(quant_data[i]==1024)
		{
			for(int j=0;j<7;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		if(quant_data[i]==2048)
		{
			for(int j=0;j<8;j++)
				encoded.push_back(1);
			encoded.push_back(0);
		}
		if(quant_data[i]==4096)
		{
			for(int j=0;j<9;j++)
				encoded.push_back(1);
		}
	}
	return encoded;
}

int* huff_decoder2(vector<int> huff_bits,int size)
{
	int* data=new int[size];
	int k=0;
	cout<<"bits size="<<huff_bits.size()<<endl;
	for(int i=0;i<size;i++)
	{
		//cout<<"i="<<i;
		//cout<<" k="<<k<<endl;



		if(huff_bits[k]==0){
			data[i]=0;
			k+=1;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==0 && huff_bits[k+2]==0){
			data[i]=2;
			k+=3;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==0){
			data[i]=4;
			k+=3;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==0 && huff_bits[k+2]==1 && huff_bits[k+3]==0){
			data[i]=8;
			k+=4;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1  && huff_bits[k+3]==0 ){
			data[i]=16;
			k+=4;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==0 && huff_bits[k+2]==1  && huff_bits[k+3]==1 && huff_bits[k+4]==0){
			data[i]=32;
			k+=5;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==0 && huff_bits[k+2]==1  && huff_bits[k+3]==1 && huff_bits[k+4]==1){
			data[i]=64;
			k+=5;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1  && huff_bits[k+4]==0){
			data[i]=128;
			k+=5;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1  && huff_bits[k+4]==1 && huff_bits[k+5]==0){
			data[i]=256;
			k+=6;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1  && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==0){
			data[i]=512;
			k+=7;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1  && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==0){
			data[i]=1024;
			k+=8;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1  && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==1 && huff_bits[k+8]==0){
			data[i]=2048;
			k+=9;
		continue;}
		else if(huff_bits[k]==1 && huff_bits[k+1]==1 && huff_bits[k+2]==1 && huff_bits[k+3]==1  && huff_bits[k+4]==1 && huff_bits[k+5]==1 && huff_bits[k+6]==1 && huff_bits[k+7]==1 && huff_bits[k+8]==1){
			data[i]=4096;
			k+=9;
		continue;}
	}
	return data;
}

//--------------------------------
// Wavelet transform
//--------------------------------
int main()
{
	Mat img=imread("lena.jpg");
	Mat gray=Mat(img.rows,img.cols,CV_8U);
	cvtColor(img,gray,CV_BGR2GRAY);

	int level=3;

	Mat enc=encoder(gray,level);
	//enc.convertTo(enc,CV_8U);
	cvNamedWindow("win1");
	imshow("win1",enc);
	//enc.convertTo(enc,CV_16U);
	/*
	Mat dec=decoder(enc,level);
	
	dec.convertTo(dec,CV_8U);
	
	cvNamedWindow("win2");  
	
	Mat diff=Mat(gray.rows,gray.cols,CV_8U);
	absdiff(gray,dec,diff);
	imshow("win2",dec);
	/*
	Mat roi;
	roi=gray(Rect(0,0,img.cols/2,img.rows/2));
	imshow("win1",roi);
	roi=gray(Rect(0,0,img.cols/4,img.rows/4));
	imshow("win2",roi);
	*/
	
	int size1=(img.rows*img.cols)/pow(2,2*level);
	//size1=5;
	int size2=img.rows*img.cols;
	cout<<size1<<" "<<size2<<endl;
	int* lp_coeff;
	lp_coeff=new int[size1];
	
	int* detail_coeff=new int[size2-size1];
	int p,q;
	p=q=0;
	//cout<<sizeof(lp_coeff);
	int max,min;
	max=-9999;
	min=9999;
	for(int i=0;i<gray.rows;i++)
	{
	//cout<<"i="<<i<<endl;
		for(int j=0;j<gray.cols;j++)
		{
			if(i<img.rows/pow(2,level) && j<img.cols/pow(2,level))
			{
				
				lp_coeff[p++]=(int)enc.at<_int16>(i,j);
				if((lp_coeff[p-1]-enc.at<_int16>(i,j))!=0)
					cout<<"i= "<<i<<" j= "<<j<<endl;
				/*
				if(max<lp_coeff[p-1])
					max=lp_coeff[p-1];
				if(min>lp_coeff[p-1])
					min=lp_coeff[p-1];
					*/
			}
			else
			{
				detail_coeff[q++]=(int)enc.at<_int16>(i,j);
				if((detail_coeff[q-1]-enc.at<_int16>(i,j))!=0)
					cout<<"i= "<<i<<" j= "<<j<<endl;
				
			}
		}
	}
	//cout<<"max="<<max;
	//cout<<"min="<<min;
	//cout<<"lp-coeff[size1-1]="<<lp_coeff[size1-1]<<endl;
	/*
	for(int i=0;i<p;i++)
	{
		cout<<lp_coeff[i]<<" ";
	}
	*/
	//getch();
	cout<<"hello"<<endl;
	int* detail_signbits=new int[size2-size1];
	
	for(int i=0;i<size2-size1;i++)
	{
		detail_signbits[i]=detail_coeff[i]>0;
		detail_coeff[i]=abs(detail_coeff[i]);
	}
	int dict[]={0,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};  //dict contains the quantisation values
	std::vector<int> detail_error_bits;  //holds the error bits for detail coefficients
	int* detail_quant_data=new int[size2-size1];  //contains the quantised deatil coefficients

	detail_encoder(detail_coeff,size2-size1,dict,&detail_error_bits,&detail_quant_data);  //encoding the detail coefficients

	
	cout<<"hello"<<endl;
	
	// now encoding  for lp coefficients using DPCM
	int* dpcm =new int[size1];
	int* dpcm_sign_bits=new int[size1];
	int* dpcm_quant_data =new int[size1];
	vector<int> dpcm_error_bits;

	 dpcm_encoder(lp_coeff,size1,dict,&dpcm,&dpcm_sign_bits,&dpcm_quant_data,&dpcm_error_bits);
	 cout<<"hello"<<endl;
	 /*
	 int c[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	for(int i=0;i<size1;i++)
	{
		if(dpcm_quant_data[i]==0)
			c[0]++;
		else
			c[(int)(log(dpcm_quant_data[i])/log(2))]++;
	}

	for(int i=0;i<16;i++)
	{
		cout<<"no."<<pow(2,i)<<" "<<c[i]<<"times"<<endl;
	}
*/	
	 vector<int> dpcm_huffbits,detail_huffbits;
	 int *dpcm_quant_data_decoded,*detail_quant_data_decoded;
	 
	 dpcm_huffbits=huff_encoder1(dpcm_quant_data,size1);
	 cout<<"abc"<<endl;
	 dpcm_quant_data_decoded=huff_decoder1(dpcm_huffbits,size1);

	 //cout<<"dpcm huff bits decoded"<<endl;
	 
	 detail_huffbits=huff_encoder2(detail_quant_data,size2-size1);
	 detail_quant_data_decoded=huff_decoder2(detail_huffbits,size2-size1);

	 cout<<"size of detail_huffbits= "<<detail_huffbits.size()<<endl;
	 cout<<"size of dpcm_huffbits= "<<dpcm_huffbits.size()<<endl;
	 cout<<"size of detail error bits= "<<detail_error_bits.size()<<endl;
	 cout<<"size of dpcm error bits= "<<dpcm_error_bits.size()<<endl;
	 
	 //cout<<"error bits size="<<dpcm_error_bits.size();
	 //cout<<"sign bit="<<dpcm_sign_bits[0]<<endl;
	 //now decoding starts
	 int* lp_coeff_decoded=new int[size1];  //holds the decoded lp coefficients
	 int* detail_coeff_decoded=new int[size2-size1];   //holds the decoded detail coefficients

	lp_coeff_decoded=dpcm_decoder(dpcm_quant_data_decoded,dpcm_sign_bits,dpcm_error_bits,size1);
	
	detail_coeff_decoded=detail_decoder(detail_quant_data_decoded,detail_error_bits,size2-size1);

	for(int i=0;i<size2-size1;i++)
	{
		detail_coeff_decoded[i]=detail_coeff_decoded[i]*pow(-1,detail_signbits[i]+1);
	}

	Mat decoded_enc=Mat(gray.rows,gray.cols,CV_16S);
	//cout<<"quant[0]="<<dpcm_quant_data[0]<<" dpcm= "<<dpcm[0]<<endl;
	cout<<"lp_coeff_decoded[size1-1]="<<lp_coeff_decoded[size1-1]<<endl;

	cout<<"detail_coeff[size1-1]="<<detail_coeff[size1-1]<<endl;
	cout<<"detail_coeff_decoded[size1-1]="<<detail_coeff_decoded[size1-1]<<endl;
	//cout<<lp_coeff[1];
	p=q=0;
	
	for(int i=0;i<gray.rows;i++)
	{
		for(int j=0;j<gray.cols;j++)
		{
			if(i<img.rows/pow(2,level) && j<img.cols/pow(2,level))
			{
				//cout<<"p="<<p<<endl;
				decoded_enc.at<_int16>(i,j)=(_int16)lp_coeff[p++];
				if((decoded_enc.at<_int16>(i,j)-lp_coeff[p-1])!=0)
					cout<<"i= "<<i<<" j= "<<j<<endl;
				/*
				if(max<lp_coeff[p-1])
					max=lp_coeff[p-1];
				if(min>lp_coeff[p-1])
					min=lp_coeff[p-1];
					*/
	}
			else
			{
				decoded_enc.at<_int16>(i,j)=(_int16)detail_coeff_decoded[q++];
				if((decoded_enc.at<_int16>(i,j)-detail_coeff_decoded[q-1])!=0)
					cout<<"i= "<<i<<" j= "<<j<<endl;
			}
		}
	}

	cout<<decoded_enc.at<_int16>(10,300)<<endl;
	cout<<enc.at<_int16>(10,300)<<endl;

	//Mat diff=Mat(gray.rows,gray.cols,CV_16S);
	//absdiff(enc,decoded_enc,diff);
	
	for(int i=0;i<gray.rows;i++)
	{
		for(int j=0;j<gray.cols;j++)
		{
			if(decoded_enc.at<_int16>(i,j)!=enc.at<_int16>(i,j))
				cout<<"i= "<<i<<" j= "<<j<<endl;
		}
	}
	
	
	//cvNamedWindow("win3");
	//decoded_enc.convertTo(decoded_enc,CV_8U);
	//imshow("win3",decoded_enc);
	Mat dec=decoder(decoded_enc,level);
	
	dec.convertTo(dec,CV_8U);
	
	cvNamedWindow("win2");
	imshow("win2",dec);
	//_getch();*/
	cvWaitKey(0);
	
	return 0;
}